package category

import (
	"BookStack/internal/domain/category"
	"BookStack/internal/domain/events"
	"BookStack/pkg/utils"
	"context"
	"fmt"
	"time"
)

// Service 分类应用服务接口
type Service interface {
	// ListCategories 获取分类列表
	ListCategories(ctx context.Context, params *CategoryListQueryParams) (*CategoryListResponse, error)
	// GetCategory 获取分类
	GetCategory(ctx context.Context, id uint) (*CategoryResponse, error)
	// GetCategoryBySlug 通过slug获取分类
	GetCategoryBySlug(ctx context.Context, slug string) (*CategoryResponse, error)
	// CreateCategory 创建分类
	CreateCategory(ctx context.Context, req *CreateCategoryRequest, userID uint) (*CategoryResponse, error)
	// UpdateCategory 更新分类
	UpdateCategory(ctx context.Context, id uint, req *UpdateCategoryRequest, userID uint) (*CategoryResponse, error)
	// DeleteCategory 删除分类
	DeleteCategory(ctx context.Context, id uint, userID uint) error
	// GetCategoryTree 获取分类树
	GetCategoryTree(ctx context.Context, categoryType int) ([]*CategoryResponse, error)
	// UpdateCategoryOrder 更新分类排序
	UpdateCategoryOrder(ctx context.Context, orders map[uint]int, userID uint) error
	// UpdateCategoryContentCount 更新分类内容数量
	UpdateCategoryContentCount(ctx context.Context, id uint, count int64) error
	// SetCategoryStatus 设置分类状态
	SetCategoryStatus(ctx context.Context, id uint, status int, userID uint) (*CategoryResponse, error)
	// MoveCategoryContent 移动分类内容
	MoveCategoryContent(ctx context.Context, id uint, targetCategoryID uint, contentIDs []uint, userID uint) error
	// AdminListCategories 管理员获取分类列表
	AdminListCategories(ctx context.Context, params *CategoryListQueryParams) (*CategoryListResponse, error)
}

// CategoryListResponse 分类列表响应
type CategoryListResponse struct {
	List  []*CategoryResponse `json:"list"`
	Total int64               `json:"total"`
}

// service 分类应用服务实现
type service struct {
	domainService  category.Service
	eventPublisher events.Publisher
}

// NewService 创建分类应用服务
func NewService(domainService category.Service, eventPublisher events.Publisher) Service {
	return &service{
		domainService:  domainService,
		eventPublisher: eventPublisher,
	}
}

// ListCategories 获取分类列表
func (s *service) ListCategories(ctx context.Context, params *CategoryListQueryParams) (*CategoryListResponse, error) {
	// 固定状态为已发布(1)
	publishedStatus := 1

	domainParams := &category.ListParams{
		Page:   params.Page,
		Size:   params.PageSize,
		Status: &publishedStatus, // 固定只返回已发布的分类（状态为1）
		Type:   params.Type,
	}

	entities, total, err := s.domainService.ListCategories(ctx, domainParams)
	if err != nil {
		fmt.Printf("查询分类失败: %v\n", err)
		return nil, err
	}

	responses := make([]*CategoryResponse, 0, len(entities))
	for _, entity := range entities {
		responses = append(responses, FromEntity(entity))
	}

	return &CategoryListResponse{List: responses, Total: total}, nil
}

// GetCategory 获取分类
func (s *service) GetCategory(ctx context.Context, id uint) (*CategoryResponse, error) {
	entity, err := s.domainService.GetCategory(ctx, id)
	if err != nil {
		return nil, err
	}
	return FromEntity(entity), nil
}

// GetCategoryBySlug 通过slug获取分类
func (s *service) GetCategoryBySlug(ctx context.Context, slug string) (*CategoryResponse, error) {
	entity, err := s.domainService.GetCategoryBySlug(ctx, slug)
	if err != nil {
		return nil, err
	}
	return FromEntity(entity), nil
}

// CreateCategory 创建分类
func (s *service) CreateCategory(ctx context.Context, req *CreateCategoryRequest, userID uint) (*CategoryResponse, error) {
	entity := req.ToEntity()
	err := s.domainService.CreateCategory(ctx, entity)
	if err != nil {
		return nil, err
	}

	// 发布事件
	event := &events.CategoryCreatedEvent{
		ID:          entity.ID,
		Name:        entity.Name,
		Slug:        entity.Slug,
		Type:        entity.Type,
		ParentID:    entity.ParentID,
		Description: entity.Description,
		Order:       entity.Order,
		Status:      entity.Status,
		CreatedBy:   userID,
		CreatedAt:   utils.TimeToJSONTime(entity.CreatedAt),
	}

	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.CategoryCreatedEventType, event))

	return FromEntity(entity), nil
}

// UpdateCategory 更新分类
func (s *service) UpdateCategory(ctx context.Context, id uint, req *UpdateCategoryRequest, userID uint) (*CategoryResponse, error) {
	entity, err := s.domainService.GetCategory(ctx, id)
	if err != nil {
		return nil, err
	}

	entity.Name = req.Name
	entity.Slug = req.Slug
	entity.Type = req.Type
	entity.ParentID = req.ParentID
	entity.Description = req.Description
	entity.Order = req.Order
	entity.Status = req.Status

	err = s.domainService.UpdateCategory(ctx, entity)
	if err != nil {
		return nil, err
	}

	// 发布事件
	event := &events.CategoryUpdatedEvent{
		ID:          entity.ID,
		Name:        entity.Name,
		Slug:        entity.Slug,
		Type:        entity.Type,
		ParentID:    entity.ParentID,
		Description: entity.Description,
		Order:       entity.Order,
		Status:      entity.Status,
		UpdatedBy:   userID,
		UpdatedAt:   utils.TimeToJSONTime(entity.UpdatedAt),
	}

	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.CategoryUpdatedEventType, event))

	return FromEntity(entity), nil
}

// DeleteCategory 删除分类
func (s *service) DeleteCategory(ctx context.Context, id uint, userID uint) error {
	// 获取分类信息用于事件
	category, err := s.domainService.GetCategory(ctx, id)
	if err != nil {
		return err
	}

	err = s.domainService.DeleteCategory(ctx, id)
	if err != nil {
		return err
	}

	// 发布事件
	event := &events.CategoryDeletedEvent{
		ID:        category.ID,
		Name:      category.Name,
		Slug:      category.Slug,
		Type:      category.Type,
		DeletedBy: userID,
		DeletedAt: utils.TimeToJSONTime(*category.DeletedAt),
	}

	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.CategoryDeletedEventType, event))

	return nil
}

// GetCategoryTree 获取分类树
func (s *service) GetCategoryTree(ctx context.Context, categoryType int) ([]*CategoryResponse, error) {
	entities, err := s.domainService.GetCategoryTree(ctx, categoryType)
	if err != nil {
		return nil, err
	}

	responses := make([]*CategoryResponse, 0, len(entities))
	for _, entity := range entities {
		responses = append(responses, FromEntity(entity))
	}

	return responses, nil
}

// UpdateCategoryOrder 更新分类排序
func (s *service) UpdateCategoryOrder(ctx context.Context, orders map[uint]int, userID uint) error {
	err := s.domainService.UpdateCategoryOrder(ctx, orders)
	if err != nil {
		return err
	}

	// 为每个更新的分类发布事件
	for id, order := range orders {
		// 获取分类信息用于事件
		category, err := s.domainService.GetCategory(ctx, id)
		if err != nil {
			continue // 跳过无法获取的分类
		}

		event := &events.CategoryOrderSetEvent{
			ID:        id,
			Order:     order,
			UpdatedBy: userID,
			UpdatedAt: utils.TimeToJSONTime(category.UpdatedAt),
		}
		s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.CategoryOrderSetEventType, event))
	}

	return nil
}

// UpdateCategoryContentCount 更新分类内容数量
func (s *service) UpdateCategoryContentCount(ctx context.Context, id uint, count int64) error {
	return s.domainService.UpdateCategoryContentCount(ctx, id, count)
}

// SetCategoryStatus 设置分类状态
func (s *service) SetCategoryStatus(ctx context.Context, id uint, status int, userID uint) (*CategoryResponse, error) {
	entity, err := s.domainService.GetCategory(ctx, id)
	if err != nil {
		return nil, err
	}

	entity.Status = status
	err = s.domainService.UpdateCategory(ctx, entity)
	if err != nil {
		return nil, err
	}

	// 发布事件
	event := &events.CategoryStatusSetEvent{
		ID:        entity.ID,
		Status:    entity.Status,
		UpdatedBy: userID,
		UpdatedAt: utils.TimeToJSONTime(entity.UpdatedAt),
	}

	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.CategoryStatusSetEventType, event))

	return FromEntity(entity), nil
}

// MoveCategoryContent 移动分类内容
func (s *service) MoveCategoryContent(ctx context.Context, id uint, targetCategoryID uint, contentIDs []uint, userID uint) error {
	// 获取源分类信息
	sourceCategory, err := s.domainService.GetCategory(ctx, id)
	if err != nil {
		return err
	}

	// 获取目标分类信息
	_, err = s.domainService.GetCategory(ctx, targetCategoryID)
	if err != nil {
		return err
	}

	// 更新内容分类
	for _, contentID := range contentIDs {
		// 根据分类类型调用不同的更新方法
		if sourceCategory.Type == 1 { // 文章分类
			err = s.domainService.UpdateArticleCategory(ctx, contentID, targetCategoryID)
		} else { // 书籍分类
			err = s.domainService.UpdateBookCategory(ctx, contentID, targetCategoryID)
		}
		if err != nil {
			return err
		}
	}

	// 发布事件
	event := &events.CategoryContentMovedEvent{
		ID:               id,
		TargetCategoryID: targetCategoryID,
		ContentIDs:       contentIDs,
		MovedBy:          userID,
		MovedAt:          utils.TimeToJSONTime(time.Now()),
	}

	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.CategoryContentMovedEventType, event))

	return nil
}

// AdminListCategories 管理员获取分类列表
func (s *service) AdminListCategories(ctx context.Context, params *CategoryListQueryParams) (*CategoryListResponse, error) {
	domainParams := &category.ListParams{
		Page:   params.Page,
		Size:   params.PageSize,
		Status: params.Status, // 允许查询所有状态
		Type:   params.Type,
	}

	entities, total, err := s.domainService.ListCategories(ctx, domainParams)
	if err != nil {
		fmt.Printf("查询分类失败: %v\n", err)
		return nil, err
	}

	responses := make([]*CategoryResponse, 0, len(entities))
	for _, entity := range entities {
		responses = append(responses, FromEntity(entity))
	}

	return &CategoryListResponse{List: responses, Total: total}, nil
}
